﻿using System;
using System.Collections.Generic;
using System.Web;
using StampController.BL;
using StampController.BL.Models;
using StampController.Core;
using log4net;

namespace StampController.Helpers
{
    public class MailHelper
    {
        private static readonly ILog logger = LogManager.GetLogger(typeof(MailHelper).Name);

        public static bool Send(ApprovalStatus status, UserType userType, UsersModel currentUser, RequestFormModel request, string url, ApprovalHistoryModel history = null)
        {
            // Init implement BL
            var usrImpl = new UsersImpl();
            var asyncSending = new AsyncSending();

            var createdUser = usrImpl.GetUser(request.UserID);
            var requestedUser = usrImpl.GetUser(request.RequestFor) ?? createdUser;

            if (requestedUser != null)
            {
                string subject, mailTo;
                switch (status)
                {
                    case ApprovalStatus.NewRequest:
                        // Mail to request by + for
                        // Cc HOD and delegate HOD
                        mailTo = requestedUser.Email;
                        subject = string.Format("New Stamp request for {0} has been submitted", requestedUser.Name);
                        // Get HOD
                        var lead = usrImpl.GetHod(request.AssignedTo);
                        // emails of delegates' HOD
                        var ccEmails = new AuthorizedHistoryImpl()
                            .GetDelegateMailList(lead.UserID, DateTime.Now) ?? new List<string>();
                        ccEmails.Add(lead.Email); // email HOD
                        if (!string.IsNullOrEmpty(request.RequestFor))
                            ccEmails.Add(createdUser.Email); // add request email (if has been request for)
                        asyncSending.SendMail(mailTo, GetBodyReplyMail(lead.Name, "http://" + HttpContext.Current.Request.Url.Authority + url, request), subject, ccEmails.ToArray());
                        break;
                    case ApprovalStatus.Approval:
                        if (userType == UserType.HOD)
                        {
                            if (history != null)
                            {
                                subject = string.Format("The Stamp request for {0} has been approved by {1}.",
                                    requestedUser.Name, history.Fullname);

                                // Mail to GD + delegate GD
                                var gd = usrImpl.GetGd();
                                mailTo = gd.Email;
                                ccEmails = new AuthorizedHistoryImpl().GetDelegateMailList(gd.UserID, DateTime.Now);
                                asyncSending.SendMail(mailTo, GetBodyConfirmMail(request, history, "http://" + HttpContext.Current.Request.Url.Authority + url),
                                    subject, ccEmails == null ? null : ccEmails.ToArray());
                                
                                // Mail to User
                                // Cc HOD

                                mailTo = requestedUser.Email;
                                lead = currentUser;
                                ccEmails = new List<string> { lead.Email };
                                if (!string.IsNullOrEmpty(request.RequestFor))
                                    ccEmails.Add(createdUser.Email); // add request email (if has been request for)
                                asyncSending.SendMail(mailTo, GetBodyConfirmMail(request, history, "http://" + HttpContext.Current.Request.Url.Authority + url),
                                    subject, ccEmails.ToArray());

                                //Log approvement
                                logger.Debug(currentUser.UserID + " has just approved request: " + request.ID + " created by " + request.UserID);
                            }
                        }
                        else if (userType == UserType.GD)
                        {
                            subject = string.Format("The Stamp request for {0} has been approved by {1}.",
                                requestedUser.Name, history.Fullname);

                            // Mail to request by + for
                            mailTo = requestedUser.Email;
                            lead = currentUser;
                            // Cc GD / HOD
                            ccEmails = new List<string> { lead.Email };
                            if (!string.IsNullOrEmpty(request.RequestFor))
                                ccEmails.Add(createdUser.Email); // add request email (if has been request for)
                            asyncSending.SendMail(mailTo, GetBodyConfirmMail(request, history, "http://" + HttpContext.Current.Request.Url.Authority + "/pages/ViewRequestForm.aspx"),
                                    subject, ccEmails.ToArray());

                            // Mail to AdminOfficer
                            lead = usrImpl.GetAdminOfficer(request.StampID);
                            mailTo = lead.Email;
                            //subject = string.Format("New Stamp request for {0} has been submitted",
                            //    requestedUser.Name);
                            asyncSending.SendMail(mailTo, GetBodyConfirmMail(request, history, "http://" + HttpContext.Current.Request.Url.Authority + url),
                                    subject);

                            //Log approvement
                            logger.Debug(currentUser.UserID + " has just approved request: " + request.ID + " created by " + request.UserID);
                        }

                        break;
                    case ApprovalStatus.Rejected:
                        if (history != null)
                        {
                            subject = string.Format("The Stamp request for {0} has been rejected by {1}.",
                                requestedUser.Name, history.Fullname);

                            lead = currentUser;

                            // Add the rejected by user
                            ccEmails = new List<string> { lead.Email };
                            if (userType == UserType.HOD)
                            {
                                // Mail to request by + for
                                // Cc HOD
                            }
                            else if (userType == UserType.GD)
                            {
                                // Mail to request by + for
                                // Cc GD
                            }
                            if (!string.IsNullOrEmpty(request.RequestFor))
                                ccEmails.Add(createdUser.Email); // add request email (if has been request for)
                            asyncSending.SendMail(requestedUser.Email, GetBodyConfirmMail(request, history, "http://" + HttpContext.Current.Request.Url.Authority + url),
                                subject, ccEmails.ToArray());

                            //Log rejectment
                            logger.Debug(currentUser.UserID + " has just rejected request: " + request.ID + " created by " + createdUser.UserID);
                        }
                        break;
                    case ApprovalStatus.Assigned:
                        if (userType == UserType.GD)
                        {
                            // Mail to assigned to (HOD + delegate HOD)
                            // Cc GD
                            if (history != null)
                            {
                                subject = string.Format("The Stamp request for {0} has been assigned by {1}.",
                                    requestedUser.Name, history.Fullname);
                                lead = usrImpl.GetHod(history.DeptID);
                                ccEmails = new AuthorizedHistoryImpl().GetDelegateMailList(lead.UserID, DateTime.Now) ?? new List<string>();
                                ccEmails.Add(currentUser.Email);
                                asyncSending.SendMail(lead.Email, GetBodyConfirmMail(request, history, "http://" + HttpContext.Current.Request.Url.Authority + url),
                                    subject, ccEmails.ToArray());
                                
                                //Log assignment
                                logger.Debug(currentUser.UserID + " has just assigned request: " + request.ID + " to " + lead.UserID);
                            }
                        }
                        break;
                }
            }
            return true;
        }

        public static bool Send(UsersModel toUsr, string url, RequestFormModel request, ApprovalHistoryModel history = null)
        {
            var usrImpl = new UsersImpl();
            var createdUser = usrImpl.GetUser(request.UserID);
            var usr = usrImpl.GetUser(request.RequestFor) ?? createdUser;
            if (usr != null)
            {
                var asyncSending = new AsyncSending();

                // History: 1 - approve, 2 - rejected, 3 - assign.
                if (history == null)
                {
                    // Phần này gửi không có approve + link
                    // Tao moi request
                    // Send cho HOD, kèm link approve
                    var subject = string.Format("New Stamp request for {0} has been submitted",
                        usr.Name);
                    var delegateEmails = new AuthorizedHistoryImpl().GetDelegateMailList(usr.UserID, DateTime.Now) ??
                                         new List<string>();
                    //CC cho requestby
                    delegateEmails.Add(usr.Email);
                    //Neu co request for, cc them cho requestfor
                    if (!string.IsNullOrEmpty(request.RequestFor))
                        delegateEmails.Add(createdUser.Email);
                    asyncSending.SendMail(toUsr.Email, GetBodyReplyMail(toUsr.Name, "http://" + HttpContext.Current.Request.Url.Authority + url, request), subject, delegateEmails.ToArray());
                }
                else
                {
                    // Phần này gửi có approve + link
                    string subject;
                    string[] delegateEmails = null;
                    if (history.Status == 2)
                    {
                        // Rejected
                        // Send mail to User
                        subject = string.Format("The Stamp request for {0} has been rejected by {1}.",
                            usr.Name, history.Fullname);
                    }
                    else if (request.AssignedTo != null)
                    {
                        // Send mail to Admin
                        var emailList = new AuthorizedHistoryImpl().GetDelegateMailList(usr.UserID, DateTime.Now);
                        if (emailList != null) delegateEmails = emailList.ToArray();
                        subject = string.Format("New Stamp request for {0} has been submitted",
                            usr.Name);
                    }
                    else
                    {
                        // Send to GD
                        var emailList = new AuthorizedHistoryImpl().GetDelegateMailList(usr.UserID, DateTime.Now);
                        if (emailList != null) delegateEmails = emailList.ToArray();
                        subject = string.Format("The Stamp request for {0} has been approved by {1}.",
                            usr.Name, history.Fullname);
                    }
                    asyncSending.SendMail(toUsr.Email, GetBodyConfirmMail(request, history, "http://" + HttpContext.Current.Request.Url.Authority + url), subject, delegateEmails);
                }
            }
            return true;
        }

        public static bool Send(string mailTo, AuthorizedHistoryModel delegateHistory)
        {
            var asyncSending = new AsyncSending();

            var msg = "your delegation has been removed by";
            var subject = "Your delegation has been removed by " + delegateHistory.CreatedName;
            if (delegateHistory.Active)
            {
                msg = "you have a delegation from";
                subject = "You have a delegation from " + delegateHistory.CreatedName;
            }
            asyncSending.SendMail(mailTo, GetBodyDelegateMail(msg, delegateHistory), subject);

            return true;
        }

        /// <summary>
        /// This template send for Usr, Admin and GD
        /// </summary>
        /// <param name="request"></param>
        /// <param name="history"></param>
        /// <param name="url"></param>
        /// <returns></returns>
        public static string GetBodyConfirmMail(RequestFormModel request, ApprovalHistoryModel history, string url)
        {
            // Phần có thêm thông tin phần approve + link
            string body = GetBodyReplyMail(string.Empty, url, request, history.Status == 1 ? "~/templates/requestconfirm.htm" : "~/templates/requestrejected.htm");
            body = body.Replace("[#ApprovedBy#]", history.ApprovedBy);
            body = body.Replace("[#ApprovedDate#]", history.ApprovedDateText);
            body = body.Replace("[#Comment#]", history.Comment);
            return body;
        }

        /// <summary>
        /// This template only send to HOD
        /// </summary>
        /// <param name="toUsr"></param>
        /// <param name="url"></param>
        /// <param name="request"></param>
        /// <param name="template"></param>
        /// <returns></returns>
        public static string GetBodyReplyMail(string toUsr, string url, RequestFormModel request, string template = "~/templates/requestReplied.htm")
        {
            // Phần này chung nè
            string filePath = HttpContext.Current.Server.MapPath(template);
            string body = DataHelper.ReadTemplateFile(filePath);

            body = body.Replace("[#ToUsr#]", toUsr);
            body = body.Replace("[#Usr#]", request.CreatedBy);
            body = body.Replace("[#RequestedBy#]", request.CreatedBy);
            body = body.Replace("[#RequestedFor#]", request.RequestForName);
            body = body.Replace("[#RequestedDate#]", request.DateRequest.ToShortDateString());
            if (request.DateNeeded != null)
                body = body.Replace("[#DateNeeded#]", request.DateNeeded.Value.ToShortDateString());
            body = body.Replace("[#Purpose#]", request.Purpose);
            body = body.Replace("[#Remark#]", request.Remark);
            body = body.Replace("[#DeptName#]", request.DeptName);
            body = body.Replace("[#StampedKind#]", request.StampName);
            body = body.Replace("[#StampedType#]", request.STName);
            body = body.Replace("[#link#]", string.Format("{0}?q={1}", url, request.RequestID));
            return body;
        }

        /// <summary>
        /// This template only send to HOD
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="delegateItem"></param>
        /// <param name="template"></param>
        /// <returns></returns>
        public static string GetBodyDelegateMail(string msg, AuthorizedHistoryModel delegateItem, string template = "~/templates/delegate.htm")
        {
            // Phần này chung nè
            string filePath = HttpContext.Current.Server.MapPath(template);
            string body = DataHelper.ReadTemplateFile(filePath);

            body = body.Replace("[#Msg#]", msg);
            body = body.Replace("[#Usr#]", delegateItem.CreatedName);
            body = body.Replace("[#DelegatedBy#]", delegateItem.AuthorizedBy);
            body = body.Replace("[#DelegatedFor#]", delegateItem.AuthorizedPerson);
            body = body.Replace("[#StartDate#]", delegateItem.StartDateText);
            body = body.Replace("[#EndDate#]", delegateItem.EndDateText);
            body = body.Replace("[#Remark#]", delegateItem.Remark);
            return body;
        }
    }
}